package com.mes.biz.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.mes.biz.domain.BizProductCategory;
import com.mes.biz.mapper.BizProductCategoryMapper;
import com.mes.biz.service.BizProductCategoryService;
import com.mes.common.constant.Constants;
import com.mes.common.core.domain.TreeNode;
import com.mes.common.core.service.BaseTreeServiceImpl;
import com.mes.common.exception.BizException;
import com.mes.common.utils.NumberUtils;
import com.mes.common.utils.StringUtils;
import com.mes.common.utils.uuid.IdUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 产品分类Service业务层处理
 * @author hwg
 * @email hwg
 * @date 2023-04-16
 */
@Service
@Transactional(readOnly = true)
public class BizProductCategoryServiceImpl extends BaseTreeServiceImpl<BizProductCategoryMapper, BizProductCategory> implements BizProductCategoryService
{
    private static final Logger log = LoggerFactory.getLogger(BizProductCategoryServiceImpl.class);

    private static final int ID_LIMIT = 500;

	/**
     * 获取单条数据
     * @param bizProductCategory 产品分类
     * @return 产品分类
     */
    @Override
    public BizProductCategory get(BizProductCategory bizProductCategory) {
        BizProductCategory dto = super.get(bizProductCategory);
        return dto;
    }

	/**
     * 获取单条数据
     * @param id 产品分类id
     * @return 产品分类
     */
    @Override
    public BizProductCategory get(String id) {
        BizProductCategory dto = super.get(id);
        return dto;
    }

    /**
     * 根据展开层级和父节点递归获取展示的数据
     * @param level 展开层级
     * @param id 父节点ID
     * @return
     */
    @Override
    public List<BizProductCategory> listDataByLevel(int level, String id) {
        List<BizProductCategory> listData = new ArrayList<BizProductCategory>();
        level--;
        List<BizProductCategory> childrenList = findChildListByParentId(id);
        for (BizProductCategory dto : childrenList) {
            if ("n".equals(dto.getTreeLeaf()) && level != 0) {
                dto.setChildren(this.listDataByLevel(level, dto.getId()));
            } else {
                dto.setChildren(new ArrayList<>());
            }
            listData.add(dto);
        }
        return listData;
    }

    /**
     * 根据父ID查询当前子节点集合
     * @param parentId 父节点ID
     * @return
     */
    @Override
    public List<BizProductCategory> findChildListByParentId(String parentId) {
        BizProductCategory bizProductCategory = new BizProductCategory();
        bizProductCategory.setParentId(parentId);
		List<BizProductCategory> bizProductCategoryList = super.findList(bizProductCategory);
        return bizProductCategoryList;
    }

    /**
     * 构建前端所需要树结构
     * @param level    展开层级
     * @param parentId 父节点ID
     * @return
     */
    @Override
    public List<TreeNode> buildTree(int level, String parentId){
        BizProductCategory bizProductCategory = new BizProductCategory();
		bizProductCategory.setId(StringUtils.EMPTY);
        return this.buildTreeDataExcludeChild(level, parentId, bizProductCategory);
    }

    /**
     * 递归构建前端所需要树结构
     * @param level     展开层级
     * @param parentId  父节点ID
     * @param excludeBizProductCategory 排除节点信息
     * @return
     */
	@Override
    public List<TreeNode> buildTreeDataExcludeChild(int level, String parentId, BizProductCategory excludeBizProductCategory) {
        List<TreeNode> listData = new ArrayList<TreeNode>();
        level--;
        BizProductCategory bizProductCategoryQuery = new BizProductCategory();
        bizProductCategoryQuery.setParentId(parentId);
        List<BizProductCategory> bizProductCategoryList = super.findList(bizProductCategoryQuery);
        for (BizProductCategory bizProductCategory : bizProductCategoryList) {
            if (!bizProductCategory.getId().equals(excludeBizProductCategory.getId())) {
                TreeNode treeNode = this.convertTreeNodeData(bizProductCategory);
                if ("n".equals(bizProductCategory.getTreeLeaf()) && level != 0) {
                    treeNode.setChildren(this.buildTreeDataExcludeChild(level, bizProductCategory.getId(), excludeBizProductCategory));
                } else {
                    treeNode.setChildren(null);
                }

                //判断父节点的加好是否需要展开：如果没有兄弟节点，则该父节点收起来
                if(bizProductCategory.getId().equals(excludeBizProductCategory.getParentId())){
                    if (CollectionUtils.isEmpty(treeNode.getChildren())) {
                        treeNode.setIsLeaf(true);
                    }
                }

                //不展开节点的父节点数据处理
                if (CollectionUtils.isEmpty(treeNode.getChildren())) {
                    treeNode.setChildren(null);
                }
                listData.add(treeNode);
            }
        }
        return listData;
    }

    /**
     * 保存产品分类
     * @param bizProductCategory
     * @return
     */
    @Override
    public boolean save(BizProductCategory bizProductCategory)
    {
        BizProductCategory parentBizProductCategory = mapper.get(bizProductCategory.getParentId());
        if (StringUtils.isEmpty(bizProductCategory.getId())) {
            if (null != parentBizProductCategory) {
                setTreeProperties(bizProductCategory, null, Constants.OpType.insert);
                super.save(bizProductCategory);
            } else {
                //新增根节点
                bizProductCategory.setId(IdUtils.randomUUID());
                bizProductCategory.setNewRecord(true);
                bizProductCategory.setParentIds(bizProductCategory.getId());
                // 设置当前树全路径排序
                Integer treeSort = bizProductCategory.getTreeSort();
                String treeSorts = String.format("%06d", treeSort);
                bizProductCategory.setTreeSorts(treeSorts);
                bizProductCategory.setTreeLeaf(Constants.TREE_LEAF_Y);
                // 设置当前节点级别.
                bizProductCategory.setTreeLevel(1);
                super.save(bizProductCategory);
            }
        } else {
            BizProductCategory oldBizProductCategory = mapper.get(bizProductCategory);
            List<BizProductCategory> updateChildList = new ArrayList<BizProductCategory>();
            if (isUpdateTreeProperties(bizProductCategory, oldBizProductCategory)) {
                setTreeProperties(bizProductCategory, oldBizProductCategory, Constants.OpType.update);
                updateChildList = updateChildTreeProperties(bizProductCategory, oldBizProductCategory);
                if (!CollectionUtils.isEmpty(updateChildList)) {
                    mapper.updateBizProductCategoryChildren(updateChildList);
                }
            }
            parentBizProductCategory = mapper.get(bizProductCategory.getParentId());
            // 新的父节点变更为非叶子节点
            if (!Constants.TREE_ROOT.equals(bizProductCategory.getParentId())
                    && parentBizProductCategory.getTreeLeaf().equals(Constants.TREE_LEAF_Y)) {
                parentBizProductCategory.setTreeLeaf(Constants.TREE_LEAF_N);
                super.save(parentBizProductCategory);
            }

            String oldParentId = oldBizProductCategory.getParentId();
            super.save(bizProductCategory);
            // 判断原节点是否还有子节点，否则改为叶子节点
            if (!hasChildByParentId(oldParentId)) {
                BizProductCategory oldParentBizProductCategory = mapper.get(oldParentId);
                oldParentBizProductCategory.setTreeLeaf(Constants.TREE_LEAF_Y);
                super.save(oldParentBizProductCategory);
            }
        }
        return Boolean.TRUE;
    }


    /**
     * 删除产品分类信息
     * @param bizProductCategory
     * @return
     */
    @Override
    public boolean remove(BizProductCategory bizProductCategory)
    {
        bizProductCategory = get(bizProductCategory);
        if (hasChildByParentId(bizProductCategory.getId()))
        {
            throw new BizException("存在子节点数据,不允许删除");
        }
        super.remove(bizProductCategory);
        //判断当前父节点下还是否有子节点，如果没有，则需要把父节点置为叶子节点
        BizProductCategory parentBizProductCategory = mapper.get(bizProductCategory.getParentId());
        if (findChildCountById(bizProductCategory.getParentId()) == 0) {
            parentBizProductCategory.setTreeLeaf(Constants.TREE_LEAF_Y);
            super.save(parentBizProductCategory);
        }
        return Boolean.TRUE;
    }

    /**
     * 是否存在子节点
     * @param parentId 部门ID
     * @return 结果
     */
    @Override
    public boolean hasChildByParentId(String parentId) {
        int result = findChildCountById(parentId);
        return result > 0;
    }

    /**
    * 查询子节点数量
    * @param parentId
    * @return
    */
    private Integer findChildCountById(String parentId) {
        BizProductCategory bizProductCategory = new BizProductCategory();
        bizProductCategory.setParentId(parentId);
        return mapper.findCount(bizProductCategory);
    }


    /**
     * 树表格检索
     * @param queryParams 检索对象
     * @return
     */
    @Override
    public List<BizProductCategory> searchBizProductCategoryList(BizProductCategory queryParams){
        List<BizProductCategory> bizProductCategoryList = new ArrayList<BizProductCategory>();
        List<BizProductCategory> searchNodes = mapper.searchBizProductCategoryTree(queryParams);
        if (!CollectionUtils.isEmpty(searchNodes)){
            Set<String> treeIdSet = getTreeIdByTreePath(searchNodes);
            int i = 0;
            //考虑mybatis foreach的限制，所以定义参数格式为list内还是list
            List<List<String>> idsList = new ArrayList<List<String>>();
            List<String> idList = new ArrayList<String>();
            for (String treeId : treeIdSet) {
                //当id个数超出限制后，则新new一个list来存放
                if(i % ID_LIMIT == 0 && i > 0){
                    idsList.add(idList);
                    idList = new ArrayList<String>();
                }
                idList.add(treeId);
                i++;
            }
            idsList.add(idList);
            List<BizProductCategory> allNodes = mapper.searchBizProductCategoryTreeByIds(idsList);
            bizProductCategoryList = createTreeGridData(allNodes);
        }
        return bizProductCategoryList;
    }

	/**
     * 树检索
     * @param queryParams 检索对象
     * @return
     */
    @Override
    public List<TreeNode> searchBizProductCategory(BizProductCategory queryParams){
        List<TreeNode> bizProductCategoryList = new ArrayList<TreeNode>();
        List<BizProductCategory> searchNodes = mapper.searchBizProductCategoryTree(queryParams);
        if (!CollectionUtils.isEmpty(searchNodes)){
            Set<String> treeIdSet = getTreeIdByTreePath(searchNodes);
            int i = 0;
            //考虑mybatis foreach的限制，所以定义参数格式为list内还是list
            List<List<String>> idsList = new ArrayList<List<String>>();
            List<String> idList = new ArrayList<String>();
            for (String treeId : treeIdSet) {
                //当id个数超出限制后，则新new一个list来存放
                if(i % ID_LIMIT == 0 && i > 0){
                    idsList.add(idList);
                    idList = new ArrayList<String>();
                }
                idList.add(treeId);
                i++;
            }
            idsList.add(idList);
            List<BizProductCategory> allNodes = mapper.searchBizProductCategoryTreeByIds(idsList);
            bizProductCategoryList = createTreeData(allNodes);
        }
        return bizProductCategoryList;
    }

    @Override
    public String getSelfAndSubIds(String categoryId,List<BizProductCategory> bizProductCategoryList,StringBuffer stringBuffer) {
        for(BizProductCategory bizProductCategory:bizProductCategoryList) {
            if(categoryId.equals(bizProductCategory.getId()) || categoryId.equals(bizProductCategory.getParentId())) {
                if(stringBuffer.indexOf(bizProductCategory.getId())==-1) {
                    if(stringBuffer.length()>0) {
                        stringBuffer.append(",");
                    }
                    stringBuffer.append(bizProductCategory.getId());
                    return getSelfAndSubIds(bizProductCategory.getId(),bizProductCategoryList,stringBuffer);
                }
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 根据parentIds去重
     * @param entityNodes entityNodes
     */
    private Set<String> getTreeIdByTreePath(List<BizProductCategory> entityNodes) {
        Set<String> treeIdSet = new HashSet<String>();
        for (BizProductCategory dto : entityNodes) {
            String treePath = dto.getParentIds();
            treeIdSet.addAll(Arrays.asList(treePath.split("/")));
        }
        return treeIdSet;
    }

    /**
     *  构建树形结构
     * @param entityNodes 节点集合
     * @return List<BizProductCategory>
     */
    private List<BizProductCategory> createTreeGridData(List<BizProductCategory> entityNodes) {
        List<BizProductCategory> treeList = new ArrayList<BizProductCategory>();
        for (BizProductCategory bizProductCategory : entityNodes) {
            //找到根节点
            if (Constants.TREE_ROOT.equals(bizProductCategory.getParentId())) {
                treeList.add(bizProductCategory);
            }
            List<BizProductCategory> children = new ArrayList<BizProductCategory>();
            //再次遍历list，找到子节点
            for (BizProductCategory node : entityNodes) {
                if (node.getParentId().equals(bizProductCategory.getId())) {
                    children.add(node);
                }
            }
            bizProductCategory.setChildren(children);
        }
        return treeList;
    }

	/**
     *  构建树形结构
     * @param entityNodes 节点集合
     * @return List<VueNode>
     */
    private List<TreeNode> createTreeData(List<BizProductCategory> entityNodes) {
        List<TreeNode> list = convertTreeNodeDatas(entityNodes);
        List<TreeNode> treeList = new ArrayList<TreeNode>();
        for (TreeNode treeNode : list) {
            //找到根节点
            if (Constants.TREE_ROOT.equals(treeNode.getParentId())) {
                treeList.add(treeNode);
            }
            List<TreeNode> children = new ArrayList<TreeNode>();
            //再次遍历list，找到子节点
            for (TreeNode node : list) {
                if (node.getParentId().equals(treeNode.getId())) {
                    children.add(node);
                }
            }
            treeNode.setChildren(children);
        }
        return treeList;
    }

	/**
     * 转换前端树节点
     * @param listData 树表格数据
     * @return
     */
    private List<TreeNode> convertTreeNodeDatas(List<BizProductCategory> listData) {
        List<TreeNode> treeNodes = new ArrayList<TreeNode>();
        for (BizProductCategory node : listData) {
            TreeNode treeNode = convertTreeNodeData(node);
            treeNodes.add(treeNode);
        }
        return treeNodes;
    }

    /**
     * 将实体类转化成前端对象格式
     * @param node 树表格对象
     * @return
     */
    private TreeNode convertTreeNodeData(BizProductCategory node) {
        TreeNode treeNode = new TreeNode();
        treeNode.setId(node.getId());
        treeNode.setKey(node.getId());
        treeNode.setTitle(node.getCategoryName());
        treeNode.setLabel(node.getCategoryName());
        treeNode.setSelectable(true);
        treeNode.setDisabled(false);
        treeNode.setDisableCheckbox(false);
        treeNode.setParentId(node.getParentId());
        treeNode.setParentIds(node.getParentIds());
        HashMap<String,Object> attr = new HashMap<>();
        attr.put("treeLeaf", node.getTreeLeaf());
        attr.put("treeLevel", node.getTreeLevel());
        attr.put("treePath", node.getParentIds());
        treeNode.setAttributes(attr);
        treeNode.setIsLeaf(Constants.TREE_LEAF_Y.equals(node.getTreeLeaf()) ? true : false);
        JSONObject slotsValue = new JSONObject();
        treeNode.setSlots(slotsValue);
        JSONObject scopedSlotsValue = new JSONObject();
		scopedSlotsValue.put("title","title");
        treeNode.setScopedSlots(scopedSlotsValue);
        return treeNode;
    }


    /**
     * 获取最大编号
     * @param bizProductCategory
     * @return
     */
    @Override
    public Integer findMaxSort(BizProductCategory bizProductCategory)
    {
        return NumberUtils.nextOrder(super.findMaxSort(bizProductCategory));
    }
}
